package com.katze.boot.plugins.redis.operations;

import com.katze.boot.plugins.redis.RedisTemplateManager;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.data.redis.core.SetOperations;

import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Function;

/**
 * 说  明：Redis 对Key-Set操作的封装
 * 作  者：zf.zeng
 * 日  期：2021-03-11 (星期四)
 **/
public class RedisSetOperations<V> {
    private final SetOperations<String, V> setOperations;
    private RedisTemplateManager<V> manager;

    public RedisSetOperations(RedisTemplate<String, V> redisTemplate){
        this.setOperations = redisTemplate.opsForSet();
    }

    public RedisSetOperations(RedisTemplateManager<V> manager){
        this.manager = manager;
        this.setOperations = manager.primary().opsForSet();
    }

    public <R>R select(int database, Function<SetOperations<String, V>, R> function){
        return function.apply(database < 0? this.setOperations:this.manager.select(database).opsForSet());
    }

    /**
     * 添加元素
     * @param key 键
     * @param values 值
     */
    public final Long add(String key, V... values){
        return this.setOperations.add(key, values);
    }

    /**
     * 找出两个集合不同的部分
     * @param key 键
     * @param otherKey 其他键
     */
    public Set<V> difference(String key, String otherKey){
        return this.setOperations.difference(key, otherKey);
    }


    /**
     * 找出两个集合不同的部分
     * @param key 键
     * @param otherKeys 其他键
     */
    public Set<V> difference(String key, Collection<String> otherKeys){
        return this.setOperations.difference(key, otherKeys);
    }

    /**
     * 找出两个集合不同的部分，并存到destKey集合中
     * @param key 键
     * @param otherKey 其他键
     * @param destKey 目标键
     * @return 返回差集的数量
     */
    public Long differenceAndStore(String key ,String otherKey, String destKey){
        return this.setOperations.differenceAndStore(key, otherKey, destKey);
    }

    /**
     * 找出两个集合不同的部分，并存到destKey集合中
     * @param key 键
     * @param otherKeys 其他键
     * @param destKey 目标键
     * @return 返回差集的数量
     */
    public Long differenceAndStore(String key, Collection<String> otherKeys, String destKey){
        return this.setOperations.differenceAndStore(key, otherKeys, destKey);
    }

    /**
     * 删除一个或多个集合中的指定值
     * @param key 键
     * @param values 目标值
     * @return 成功删除数量
     */
    public Long remove(String key, Object ...values){
        return this.setOperations.remove(key, values);
    }

    /**
     * 随机移除一个元素,并返回出来
     * @param key 键
     */
    public V randomSetPop(String key){
        return this.setOperations.pop(key);
    }

    /**
     * 随机获取一个元素
     * @param key 键
     */
    public V randomSet(String key){
        return this.setOperations.randomMember(key);
    }

    /**
     * 将key中的value转到destKey中
     * @param key 键
     * @param value 值
     * @param destKey 目标键
     * @return 返回成功与否
     */
    public Boolean moveSet(String key,V value,String destKey){
        return this.setOperations.move(key, value, destKey);
    }

    /**
     * 无序集合的大小
     * @param key 键
     */
    public Long setSize(String key){
        return this.setOperations.size(key);
    }

    /**
     * 判断set集合中是否有value
     * @param key 键
     * @param value 目标值
     */
    public Boolean isMember(String key,Object value){
        return this.setOperations.isMember(key, value);
    }

    /**
     * 返回key和othere 的并集
     * @param key 键
     * @param otherKey 其他键
     */
    public Set<V> unionSet(String key,String otherKey){
        return this.setOperations.union(key, otherKey);
    }

    /**
     * 返回key和otherKeys的并集
     * @param key 键
     * @param otherKeys 其他键
     */
    public Set<V> unionSet(String key, Collection<String> otherKeys){
        return this.setOperations.union(key, otherKeys);
    }

    /**
     * 将 key 与 otherKey 的并集,保存到 destKey 中
     * @param key 键
     * @param otherKey 其他键
     * @param destKey 目标键
     */
    public Long unionAndStoreSet(String key, String otherKey,String destKey){
        return this.setOperations.unionAndStore(key, otherKey, destKey);
    }

    /**
     * 将 key与otherKey的并集,保存到destKey 中
     * @param key 键
     * @param otherKeys 其他键
     * @param destKey 目标键
     * @return destKey 数量
     */
    public Long unionAndStoreSet(String key, Collection<String> otherKeys, String destKey){
        return this.setOperations.unionAndStore(key, otherKeys, destKey);
    }

    /**
     * 返回集合中所有元素
     * @param key 键
     */
    public Set<V> members(String key){
        return this.setOperations.members(key);
    }

    /**
     * 扫描指定key下的数据集
     * @param key 集合键
     * @param matchKey 匹配关键字 模糊查询：*123，*
     */
    public Set<V> scan(String key, String matchKey) {
        Set<V> data = new HashSet<>();
        try(Cursor<V> cursor = this.setOperations.scan(key, ScanOptions.scanOptions().match(matchKey).count(1000).build())) {
            while (cursor.hasNext()){
                V entry = cursor.next();
                data.add(entry);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return data;
    }
}
